"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebSocketClient = void 0;
const Logger_1 = require("../utils/Logger");
const SocketClientReqManager_1 = require("./SocketClientReqManager");
const SocketRequestData_1 = require("./SocketRequestData");
const WebSocketClientManager_1 = require("./WebSocketClientManager");
const ProtoManager_1 = require("../../lib/net/protobuf/ProtoManager");
const jhaoproto_1 = require("../../lib/net/protobuf/jhaoproto");
const DateUtil_1 = require("../utils/DateUtil");
const ws = require("ws");
class WebSocketClient {
    constructor() {
        this.requestMsgQue = [];
        this.reqId = 1;
        this.requestMsgMap = new Map();
    }
    init(url, id) {
        try {
            if (!this.isConnected && !this.isConnecting) {
                this.isConnecting = true;
                this.url = url;
                this.id = id;
                this.ws = new ws(url);
                Logger_1.Logger.log("WebSocketClient===init=", url, this.id);
                this.ws.on('open', () => {
                    WebSocketClient.count++;
                    this.isConnecting = false;
                    Logger_1.Logger.info("ws onConnect===", this.url, this.id, WebSocketClient.count);
                    this.isConnected = true;
                    this.checkSendPack();
                });
                this.ws.on('message', (socketData) => {
                    this.onGameMsg(socketData);
                });
                this.ws.on("error", (err) => {
                    this.isConnected = false;
                    this.isConnecting = false;
                    Logger_1.Logger.error("WebSocketClient error=====", this.id, err);
                });
                this.ws.on('close', () => {
                    this.isConnected = false;
                    this.isConnecting = false;
                    Logger_1.Logger.info('disconnected', this.id, this.url);
                    this.destroy();
                });
            }
        }
        catch (error) {
            Logger_1.Logger.error("WebSocketClient error=", error);
        }
    }
    onGameMsg(socketData) {
        try {
            let byteArray = new Uint8Array(socketData);
            let baseMsg = ProtoManager_1.ProtoManager.instance.decode(jhaoproto_1.JhaoProto.BaseMsg, byteArray);
            let socketReqData = this.requestMsgMap.get(baseMsg.cmdOrder);
            if (socketReqData) {
                this.requestMsgMap.delete(baseMsg.cmdOrder);
                if (socketReqData.data.callback) {
                    socketReqData.data.callback(baseMsg);
                }
                else {
                    SocketClientReqManager_1.SocketClientReqManager.instance.onSocketMsg(this, baseMsg);
                }
            }
            else {
                SocketClientReqManager_1.SocketClientReqManager.instance.onSocketMsg(this, baseMsg);
            }
        }
        catch (error) {
            Logger_1.Logger.error("onGameMsg======error==", error);
            this.destroy();
        }
    }
    sendDataAsync(protoPack) {
        return __awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => {
                this.sendData(protoPack, (data) => {
                    resolve(data);
                });
            });
        });
    }
    sendData(protoPack, callback = null) {
        let reqData = new SocketRequestData_1.default();
        reqData.id = this.reqId;
        this.reqId++;
        reqData.data = protoPack;
        reqData.callback = callback;
        this.requestMsgQue.push(reqData);
        if (this.isConnected) {
            this.checkSendPack();
        }
        else {
            this.init(this.url, this.id);
        }
    }
    checkOnlyId() {
        let abc = this.reqId;
        this.reqId++;
        if (this.reqId >= Number.MAX_SAFE_INTEGER) {
            this.reqId = 1;
        }
        return abc;
    }
    sendProto(sendData) {
        let reqData = new SocketRequestData_1.default();
        reqData.id = this.checkOnlyId();
        reqData.data = sendData;
        this.requestMsgQue.push(reqData);
        Logger_1.Logger.log("sendProto==", sendData, this.requestMsgQue);
        if (this.isConnected) {
            this.checkSendPack();
        }
        else {
            if (!this.isConnecting) {
                this.init(this.url, this.id);
            }
        }
    }
    checkSendPack() {
        if (this.requestMsgQue.length > 0) {
            if (this.isConnected) {
                let socketData = this.requestMsgQue.shift();
                this.send(this.createSendPack(socketData));
                this.checkSendPack();
            }
            else {
                if (!this.isConnecting) {
                    this.init(this.url, this.id);
                }
            }
        }
    }
    /**
 * 创建发送包
 * @param protoPack
 */
    createSendPack(socketData) {
        // let data: object = {
        //     "id": socketData.id,
        //     "data": socketData.data
        // }
        // this.respCheckMap.set(socketData.id, socketData)
        // return JSON.stringify(data)
        let send_data = {
            cmdOrder: socketData.id,
            cmdIndex: socketData.data.cmd_index,
            timeUpload: DateUtil_1.default.now(),
            data: ProtoManager_1.ProtoManager.instance.encode(socketData.data.en_proto_ctor, socketData.data.data)
        };
        this.requestMsgMap.set(socketData.id, socketData);
        return ProtoManager_1.ProtoManager.instance.encode(jhaoproto_1.JhaoProto.BaseMsg, send_data);
    }
    send(data) {
        if (this.isConnected) {
            this.ws.send(data);
        }
    }
    close() {
        if (this.isConnected) {
            Logger_1.Logger.log("WebSocketClient.close");
            this.ws.close();
        }
    }
    destroy() {
        if (!this.isDestroy) {
            this.isConnecting = false;
            this.isConnected = false;
            this.isDestroy = true;
            WebSocketClientManager_1.WebSocketClientManager.instance.destoyWebSocketClient(this);
            this.account = null;
            this.ws.removeAllListeners();
            this.ws = null;
            this.requestMsgMap.clear();
            this.requestMsgMap = null;
            this.requestMsgQue = null;
        }
    }
}
exports.WebSocketClient = WebSocketClient;
WebSocketClient.count = 0;
